# By: Riasat Ullah
# This file serves routine related pages and data.

from constants import api_paths, component_names as cnm, label_names as lnm, pages, static_vars, var_names
from context_manager import configurations_context, tutorials_context
from django.core import exceptions
from django.http import HttpResponse, JsonResponse
from django.shortcuts import redirect, render
from django.views.decorators.http import require_http_methods
from taskcallweb import settings
from system_tests.test_data import test_data_policies, test_data_organization
from translators import label_translator as lt
from urllib.parse import urlencode
from utils import helpers, logging
from validations import request_validator
import json


@require_http_methods(['GET', 'POST'])
def get_routines(request):
    '''
    GET: Returns the list of routines page.
    POST: Gets the list of routines.
    :param request: Http request
    :return: Http response
    '''
    if request.method == 'GET':
        if request_validator.user_in_session(request):
            lang = request_validator.get_user_language(request)
            nav_bar_components = request_validator.get_nav_bar_components(request)

            has_view_perm, has_edit_perm = request_validator.get_session_permission(
                request, cnm.dis_com_routines, nav_bar_components
            )
            if not has_view_perm:
                raise exceptions.PermissionDenied

            context = configurations_context.get_routine_list_context(lang, nav_bar_components)
            context[var_names.has_edit_permission] = has_edit_perm
            return render(request, pages.routine_list_page, context=context)
        else:
            helpers.set_session_redirect_page(request)
            return redirect(pages.login_url)
    elif request.method == 'POST':
        lang = request_validator.get_user_language(request)
        if request_validator.user_in_session(request):
            if settings.TEST_MODE:
                return JsonResponse(test_data_policies.routines_list, safe=False)
            else:
                body = dict()
                status, output = helpers.post_api_request(api_paths.routines_list, body, request, lang=lang)
                return JsonResponse(output, status=status, safe=False)
        else:
            return JsonResponse(lt.get_label(lnm.err_unauthorized_access, lang), status=401, safe=False)


@require_http_methods(['GET', 'POST'])
def get_routine_details(request, routine_ref_id=None):
    '''
    GET: Returns the routine details page.
    POST: Gets the routine details.
    :param request: Http request
    :param routine_ref_id: the reference ID of the group
    :return: JSON response
    '''
    if request.method == 'GET':
        if request_validator.user_in_session(request):
            try:
                lang = request_validator.get_user_language(request)
                nav_bar_components = request_validator.get_nav_bar_components(request)

                has_view_perm, has_edit_perm = request_validator.get_session_permission(
                    request, cnm.dis_com_routines, nav_bar_components
                )
                if not has_view_perm or (routine_ref_id is None and not has_edit_perm):
                    raise exceptions.PermissionDenied

                context = configurations_context.get_routine_details_context(lang, nav_bar_components)
                context[var_names.context] = json.dumps({var_names.routine_ref_id: routine_ref_id})
                context[var_names.has_edit_permission] = has_edit_perm
                context[var_names.has_component_flexible_role] =\
                    True if cnm.feat_users_component_flexible_role in request_validator.get_component_features(request)\
                    else False

                context = {**context, **tutorials_context.get_onboarding_routine_context(lang)}

                if 'flow' in request.GET:
                    context[var_names.flow_id] = request.GET.get('flow')
                if 'step' in request.GET:
                    context[var_names.step_number] = request.GET.get('step')
                if 'tutorial' in request.GET:
                    context[var_names.tutorial_name] = request.GET.get('tutorial')

                return render(request, pages.routine_details_page, context=context)
            except ValueError as e:
                logging.exception(str(e))
                return render(request, pages.routine_list_page)
        else:
            helpers.set_session_redirect_page(request)
            return redirect(pages.login_url)
    elif request.method == 'POST':
        lang = request_validator.get_user_language(request)
        if request_validator.user_in_session(request):
            if settings.TEST_MODE:
                return JsonResponse(test_data_policies.routine_details[routine_ref_id], safe=False)
            else:
                body = {var_names.routine_ref_id: routine_ref_id}
                status, output = helpers.post_api_request(api_paths.routines_details, body, request, lang=lang)
                return JsonResponse(output, status=status, safe=False)
        else:
            return JsonResponse(lt.get_label(lnm.err_unauthorized_access, lang), status=401, safe=False)


@require_http_methods(['POST'])
def get_multiple_routines(request):
    '''
    Gets details of multiple routines at once.
    :param request: Http request
    :return: JSON response
    '''
    if request.method == 'POST':
        lang = request_validator.get_user_language(request)
        if request_validator.user_in_session(request):
            body = json.loads(request.body.decode())
            if settings.TEST_MODE:
                routine_ids = body[var_names.routine_ref_id]
                routines = dict()
                for id_ in routine_ids:
                    routines[id_] = test_data_policies.routine_details[id_]
                return JsonResponse(routines, safe=False)
            else:
                status, output = helpers.post_api_request(api_paths.routines_multiple, body, request, lang=lang)
                return JsonResponse(output, status=status, safe=False)
        else:
            return JsonResponse(lt.get_label(lnm.err_unauthorized_access, lang), status=401, safe=False)


@require_http_methods(['POST'])
def create_routine(request):
    '''
    Creates a new routine.
    :param request: Http request
    :return: JSON response
    '''
    if request.method == 'POST':
        lang = request_validator.get_user_language(request)
        if request_validator.user_in_session(request):
            body = json.loads(request.body.decode())
            if settings.TEST_MODE:
                return JsonResponse('New routine has been created', safe=False)
            else:
                status, output = helpers.post_api_request(api_paths.routines_create, body, request, lang=lang)
                return JsonResponse(output, status=status, safe=False)
        else:
            return JsonResponse(lt.get_label(lnm.err_unauthorized_access, lang), status=401, safe=False)


@require_http_methods(['POST'])
def edit_routine(request):
    '''
    Edits an existing routine.
    :param request: Http request
    :return: JSON response
    '''
    if request.method == 'POST':
        lang = request_validator.get_user_language(request)
        if request_validator.user_in_session(request):
            body = json.loads(request.body.decode())
            if settings.TEST_MODE:
                return JsonResponse('Routine has been edited', safe=False)
            else:
                status, output = helpers.post_api_request(api_paths.routines_edit, body, request, lang=lang)
                return JsonResponse(output, status=status, safe=False)
        else:
            return JsonResponse(lt.get_label(lnm.err_unauthorized_access, lang), status=401, safe=False)


@require_http_methods(['POST'])
def delete_routine(request):
    '''
    Deletes an existing routine.
    :param request: Http request
    :return: JSON response
    '''
    if request.method == 'POST':
        lang = request_validator.get_user_language(request)
        if request_validator.user_in_session(request):
            body = json.loads(request.body.decode())
            if settings.TEST_MODE:
                return JsonResponse('Routine has been deleted', safe=False)
            else:
                status, output = helpers.post_api_request(api_paths.routines_delete, body, request, lang=lang)
                return JsonResponse(output, status=status, safe=False)
        else:
            return JsonResponse(lt.get_label(lnm.err_unauthorized_access, lang), status=401, safe=False)


@require_http_methods(['POST'])
def get_routine_history(request, routine_ref_id=None):
    '''
    Get historical routine.
    :param request: Http request
    :param routine_ref_id: reference ID of the routine
    :return: Http response
    '''
    if request.method == 'POST':
        lang = request_validator.get_user_language(request)
        if request_validator.user_in_session(request):
            nav_bar_components = request_validator.get_nav_bar_components(request)
            has_view_perm, has_edit_perm = request_validator.get_session_permission(
                request, cnm.dis_com_routines, nav_bar_components
            )
            if not has_view_perm:
                raise exceptions.PermissionDenied

            body = json.loads(request.body.decode())
            if settings.TEST_MODE:
                status, output = 200, test_data_policies.routine_schedule
            else:
                status, output = helpers.post_api_request(api_paths.routines_shifts, body, request)

            return JsonResponse(output, status=status, safe=False)
        else:
            return JsonResponse(lt.get_label(lnm.err_unauthorized_access, lang), status=401, safe=False)


@require_http_methods(['GET'])
def get_routine_ics(request, routine_ref_id=None):
    '''
    Gets the ics (calendar) file of a routine.
    :param request: Http request
    :param routine_ref_id: reference ID of the routine
    :return: Http response
    '''
    if request.method == 'GET':
        lang = request_validator.get_user_language(request)
        if request_validator.user_in_session(request):
            nav_bar_components = request_validator.get_nav_bar_components(request)
            has_view_perm, has_edit_perm = request_validator.get_session_permission(
                request, cnm.dis_com_routines, nav_bar_components
            )
            if not has_view_perm:
                raise exceptions.PermissionDenied

            start_date = request.GET[var_names.start_date]
            end_date = request.GET[var_names.end_date]
            body = {
                var_names.routine_ref_id: routine_ref_id,
                var_names.start_date: start_date,
                var_names.end_date: end_date,
                var_names.timezone: request.GET[var_names.timezone]
            }
            if settings.TEST_MODE:
                status, output = 200, test_data_policies.routine_schedule
            else:
                status, output = helpers.post_api_request(api_paths.routines_shifts, body, request)

            if status == 200:
                try:
                    ics = helpers.prepare_calendar(output[var_names.data], output[var_names.timezone],
                                                   output[var_names.display_name])
                    if ics:
                        response = HttpResponse(ics, content_type='text/calendar')
                        filename = output[var_names.display_name] + ' ' + start_date + ' - ' + end_date + '.ics'
                        content = "attachment; filename={0}".format(filename)
                        response['Content-Disposition'] = content
                        return response
                    return JsonResponse(lt.get_label(lnm.err_calendar_download, lang), status=500, safe=False)
                except Exception as e:
                    logging.exception(str(e))
                    return JsonResponse(lt.get_label(lnm.err_calendar_download, lang), status=500, safe=False)
            else:
                return JsonResponse(lt.get_label(lnm.err_calendar_download, lang), status=500, safe=False)
        else:
            return JsonResponse(lt.get_label(lnm.err_unauthorized_access, lang), status=401, safe=False)


@require_http_methods(['POST'])
def get_routine_webcal_url(request, routine_ref_id=None):
    '''
    Gets the URL of the WebCal feed of a user.
    :param request: Http request
    :param routine_ref_id: reference ID of the routine
    :return: Http response
    '''
    if request.method == 'POST':
        lang = request_validator.get_user_language(request)
        if request_validator.user_in_session(request):
            nav_bar_components = request_validator.get_nav_bar_components(request)
            has_view_perm, has_edit_perm = request_validator.get_session_permission(
                request, cnm.dis_com_routines, nav_bar_components
            )
            if not has_view_perm:
                return JsonResponse(lt.get_label(lnm.err_unauthorized_access, lang), status=401, safe=False)

            body = {var_names.routine_ref_id: routine_ref_id}
            if settings.TEST_MODE:
                status, output = 200, {
                    var_names.routine_ref_id: test_data_policies.routines_list[0][var_names.routine_ref_id],
                    var_names.subdomain: test_data_organization.organization_details[var_names.subdomain],
                    var_names.account_id: test_data_organization.organization_details[var_names.account_id]
                }
            else:
                status, output = helpers.post_api_request(api_paths.routines_webcal_info, body, request)

            if status == 200:
                ref_dict = static_vars.regional_urls
                if settings.TEST_SERVER:
                    ref_dict = static_vars.regional_test_server_urls
                cal_root = '{0}/public/{1}/{2}/on-call-shifts?'.format(
                    ref_dict[settings.REGION][var_names.redirect_base], output[var_names.subdomain],
                    output[var_names.account_id]
                )
                params = {var_names.routines: output[var_names.routine_ref_id]}
                cal_url = cal_root + urlencode(params)
                return JsonResponse(cal_url, safe=False)
            else:
                return JsonResponse(lt.get_label(lnm.err_unauthorized_access, lang), status=401, safe=False)
        else:
            return JsonResponse(lt.get_label(lnm.err_unauthorized_access, lang), status=401, safe=False)
