# By: Riasat Ullah
# This file contains functions for the pages that are intended for reports.

from constants import api_paths, component_names as cnm, label_names as lnm, pages, static_vars, var_names
from context_manager import analytics_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_analytics
from translators import label_translator as lt
from utils import logging, helpers, test_data
from validations import request_validator
import datetime
import json
import random
import string


@require_http_methods(['GET', 'POST'])
def list_postmortem_reports(request):
    '''
    GET: Gets the page to display postmortem reports.
    POST: Gets the list of all the available postmortem reports for a given user.
    :param request: Http request
    :return: GET: Http response  |  POST: JSON 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 = request_validator.has_view_permission(request, cnm.dis_com_postmortem, nav_bar_components)
            if not has_view_perm:
                raise exceptions.PermissionDenied

            context = analytics_context.get_postmortem_list_context(lang, nav_bar_components)
            return render(request, pages.postmortem_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_analytics.postmortem_reports, safe=False)
            else:
                body = dict()
                status, output = helpers.post_api_request(api_paths.postmortem_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_postmortem_report(request, org_instance_id=None, report_number=None):
    '''
    GET: Gets the postmortem report details page.
    POST: Gets all the details for a specific postmortem report.
    :param request: Http request
    :param org_instance_id: ID of the instance (incident) this request is being made for;
                        this will be needed for new reports
    :param report_number: the report number
    :return: GET: Http response  |  POST: JSON response
    '''
    if request.method == 'GET':
        if request_validator.user_in_session(request):
            try:
                if org_instance_id is not None:
                    org_instance_id = int(org_instance_id)

                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_postmortem, nav_bar_components
                )
                if not has_view_perm:
                    raise exceptions.PermissionDenied

                context = analytics_context.get_postmortem_report_context(lang, nav_bar_components)
                context[var_names.has_edit_permission] = has_edit_perm
                context[var_names.context] = json.dumps({var_names.report_number: report_number,
                                                         var_names.organization_instance_id: org_instance_id})
                return render(request, pages.postmortem_report_page, context=context)
            except ValueError as e:
                logging.exception(str(e))
                return render(request, pages.postmortem_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_analytics.postmortem_report_details[report_number], safe=False)
            else:
                body = {var_names.report_number: report_number}
                status, output = helpers.post_api_request(api_paths.postmortem_report, 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_postmortem_report(request):
    '''
    Creates a new postmortem report.
    :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(''.join([random.choice(string.ascii_uppercase) for _ in range(0, 8)]), safe=False)
            else:
                status, output = helpers.post_api_request(api_paths.postmortem_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 save_postmortem_report(request):
    '''
    Save changes made to an already existing postmortem report.
    :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('Report has been saved', safe=False)
            else:
                status, output = helpers.post_api_request(api_paths.postmortem_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 save_postmortem_report_comment(request):
    '''
    Save a comment made on a postmortem report.
    :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:
                response_data = [datetime.datetime.now(), 'Lewis Johnson']
                return JsonResponse(response_data, safe=False)
            else:
                status, output = helpers.post_api_request(api_paths.postmortem_comment, 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_postmortem_report(request):
    '''
    Delete a postmortem report.
    :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('Postmortem report has been deleted', safe=False)
            else:
                status, output = helpers.post_api_request(api_paths.postmortem_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(['GET'])
def get_postmortem_pdf(request, report_number):
    '''
    Gets the pdf of a postmortem report.
    :param request: Http request
    :param report_number: the unique number of the postmortem report
    :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_postmortem, nav_bar_components
            )
            if not has_edit_perm:
                raise exceptions.PermissionDenied

            context = analytics_context.get_postmortem_template_context(lang)
            if settings.TEST_MODE:
                report_details = list(test_data.postmortem_report_details.values())[0]
                incident_details = test_data.incident_details[report_details[var_names.organization_instance_id]]
            else:
                report_request_body = {var_names.report_number: report_number}
                report_request_status, report_details = helpers.post_api_request(
                    api_paths.postmortem_report, report_request_body, request, lang=lang
                )
                if report_request_status == 200:
                    incident_request_body = {
                        var_names.organization_instance_id: report_details[var_names.organization_instance_id]
                    }
                    incident_request_status, incident_details = helpers.post_api_request(
                        api_paths.incidents_details, incident_request_body, request, lang=lang
                    )
                    if incident_request_status != 200:
                        logging.error('Failed to get incident details - Status ' + str(incident_request_status))
                        logging.error(incident_details)
                        return JsonResponse(incident_details, status=incident_request_status, safe=False)
                else:
                    logging.error('Failed to get report details - Status ' + str(report_request_status))
                    logging.error(report_details)
                    return JsonResponse(report_details, status=report_request_status, safe=False)

            if report_details is not None and incident_details is not None:
                report_context = helpers.contextualize_postmortem(report_details, incident_details)

                rep_status = report_context[var_names.status]
                inc_urgency = report_context[var_names.incident][var_names.task][var_names.urgency_level]
                inc_status = report_context[var_names.incident][var_names.status]

                report_status_map = {
                    'ALL': context[lnm.det_all],
                    'DRAFT': context[lnm.det_draft],
                    'IN_REVIEW': context[lnm.det_in_review],
                    'REVIEWED': context[lnm.det_reviewed],
                    'CLOSED': context[lnm.det_closed]
                }
                incident_status_map = {
                    static_vars.acknowledged_state: context[lnm.sts_acknowledged],
                    static_vars.cancelled_state: context[lnm.sts_cancelled],
                    static_vars.open_state: context[lnm.sts_open],
                    static_vars.resolved_state: context[lnm.sts_resolved],
                }
                urgency_map = {
                    static_vars.minor_urgency: context[lnm.opt_minor],
                    static_vars.low_urgency: context[lnm.opt_low],
                    static_vars.medium_urgency: context[lnm.opt_medium],
                    static_vars.high_urgency: context[lnm.opt_high],
                    static_vars.critical_urgency: context[lnm.opt_critical]
                }

                report_context[var_names.status] = report_status_map[rep_status]
                report_context[var_names.incident][var_names.task][var_names.urgency_level] = urgency_map[inc_urgency]
                report_context[var_names.incident][var_names.status] = incident_status_map[inc_status]

                context = {**context, **report_context}
                try:
                    pdf = helpers.render_to_pdf('tmpl_postmortem_pdf.html', context)
                    if pdf:
                        response = HttpResponse(pdf, content_type='application/pdf')
                        filename = 'Postmortem_Report_' + context[var_names.report_number] + '.pdf'
                        content = "attachment; filename={0}".format(filename)
                        response['Content-Disposition'] = content
                        return response
                    return JsonResponse(lt.get_label(lnm.err_postmortem_download, lang), status=500, safe=False)
                except Exception as e:
                    logging.exception(str(e))
                    return JsonResponse(lt.get_label(lnm.err_postmortem_download, lang), status=500, safe=False)
            else:
                return JsonResponse(lt.get_label(lnm.err_postmortem_download, lang), status=500, safe=False)
        else:
            return JsonResponse(lt.get_label(lnm.err_unauthorized_access, lang), status=401, safe=False)
