# By: Riasat Ullah
# This file contains functions related to status dashboard views.

from dbqueries import db_status_dashboards
from exceptions.user_exceptions import InvalidRequest, UnauthorizedRequest
from rest_framework.decorators import api_view
from rest_framework.response import Response
from translators import label_translator as _lt
from utils import errors, info, logging, permissions, times, tokenizer, var_names
from utils.db_connection import CONN_POOL
from validations import request_validator
import jwt


@api_view(['POST'])
def get_dashboard(request, conn=None):
    '''
    Create the dashboard for all business services of the organization (the general dashboard).
    :param request: Http request
    :param conn: db connection
    :return: JSON response
    '''
    if request.method == 'POST':
        lang = request_validator.get_user_language(request)
        optional_fields = [var_names.dashboard_url]
        try:
            conn = CONN_POOL.get_db_conn() if conn is None else conn
            request_validator.validate_fields(request, [], optional_fields)
            user_id, org_id, user_perm, org_perm = tokenizer.authorize_request(request)

            if not permissions.has_org_permission(org_perm, permissions.ORG_STATUS_DASHBOARDS_PERMISSION):
                return Response(_lt.get_label(errors.err_subscription_rights, lang), status=403)
            if not permissions.has_user_permission(user_perm, permissions.USER_STATUS_DASHBOARD_VIEW_PERMISSION):
                return Response(_lt.get_label(errors.err_user_rights, lang), status=403)

            current_time = times.get_current_timestamp()
            impacted_bus_names = []
            custom_dash = []
            dash_name = None
            dash_url = request.data[var_names.dashboard_url] if var_names.dashboard_url in request.data else None

            bus_servs = db_status_dashboards.get_dashboard_business_services_impact_status(
                conn, current_time, org_id, dashboard_url=dash_url, user_id=user_id)

            if permissions.has_org_permission(org_perm, permissions.ORG_STATUS_DASHBOARDS_CREATE_PERMISSION):
                custom_dash = db_status_dashboards.get_custom_status_dashboards(conn, current_time, org_id)
                if dash_url is not None:
                    for item in custom_dash:
                        if item[1] == dash_url:
                            dash_name = item[0]
                            break

                    # if url is not found in custom dashboards, then it must be incorrect
                    if dash_name is None:
                        raise InvalidRequest(errors.err_unknown_resource)

            for item in bus_servs:
                if len(item[var_names.incidents]) > 0:
                    impacted_bus_names.append(item[var_names.service_name])

            data = {
                var_names.dashboards: custom_dash,
                var_names.dashboard_url: dash_url,
                var_names.dashboard_name: dash_name,
                var_names.is_healthy: True if len(impacted_bus_names) == 0 else False,
                var_names.status: _lt.get_label(info.msg_status_dashboard_healthy, lang) if len(impacted_bus_names) == 0
                else ', '.join(impacted_bus_names) + ' ' + _lt.get_label(info.msg_status_dashboard_impacted, lang),
                var_names.business_services: bus_servs
            }

            return Response(data)
        except InvalidRequest as e:
            logging.exception(str(e))
            return Response(_lt.get_label(str(e), lang), status=400)
        except (UnauthorizedRequest, jwt.ExpiredSignatureError, jwt.InvalidSignatureError) as e:
            logging.exception(str(e))
            return Response(_lt.get_label(errors.err_authorization, lang), status=401)
        except Exception as e:
            logging.exception(str(e))
            return Response(_lt.get_label(errors.err_system_error, lang), status=500)
        finally:
            CONN_POOL.put_db_conn(conn)


@api_view(['POST'])
def create_custom_dashboard(request, conn=None):
    '''
    Create a status dashboard.
    :param request: Http request
    :param conn: db connection
    :return: JSON response
    '''
    if request.method == 'POST':
        lang = request_validator.get_user_language(request)
        expected_fields = [var_names.dashboard_url, var_names.dashboard_name, var_names.business_services]
        try:
            conn = CONN_POOL.get_db_conn() if conn is None else conn
            request_validator.validate_fields(request, expected_fields)
            user_id, org_id, user_perm, org_perm = tokenizer.authorize_request(request)

            if not permissions.has_org_permission(org_perm, permissions.ORG_STATUS_DASHBOARDS_CREATE_PERMISSION):
                return Response(_lt.get_label(errors.err_subscription_rights, lang), status=403)
            if not permissions.has_user_permission(user_perm, permissions.USER_STATUS_DASHBOARD_EDIT_PERMISSION):
                return Response(_lt.get_label(errors.err_user_rights, lang), status=403)

            db_status_dashboards.create_custom_status_dashboard(
                conn, times.get_current_timestamp(), org_id, request.data[var_names.dashboard_name],
                request.data[var_names.dashboard_url], request.data[var_names.business_services]
            )

            return Response(_lt.get_label(info.msg_status_dashboard_created, lang))
        except InvalidRequest as e:
            logging.exception(str(e))
            return Response(_lt.get_label(str(e), lang), status=400)
        except (UnauthorizedRequest, jwt.ExpiredSignatureError, jwt.InvalidSignatureError) as e:
            logging.exception(str(e))
            return Response(_lt.get_label(errors.err_authorization, lang), status=401)
        except Exception as e:
            logging.exception(str(e))
            return Response(_lt.get_label(errors.err_system_error, lang), status=500)
        finally:
            CONN_POOL.put_db_conn(conn)


@api_view(['POST'])
def edit_custom_dashboard(request, conn=None):
    '''
    Create a status dashboard.
    :param request: Http request
    :param conn: db connection
    :return: JSON response
    '''
    if request.method == 'POST':
        lang = request_validator.get_user_language(request)
        expected_fields = [var_names.url, var_names.dashboard_url, var_names.dashboard_name,
                           var_names.business_services]
        try:
            conn = CONN_POOL.get_db_conn() if conn is None else conn
            request_validator.validate_fields(request, expected_fields)
            user_id, org_id, user_perm, org_perm = tokenizer.authorize_request(request)

            if not permissions.has_org_permission(org_perm, permissions.ORG_STATUS_DASHBOARDS_CREATE_PERMISSION):
                return Response(_lt.get_label(errors.err_subscription_rights, lang), status=403)
            if not permissions.has_user_permission(user_perm, permissions.USER_STATUS_DASHBOARD_EDIT_PERMISSION):
                return Response(_lt.get_label(errors.err_user_rights, lang), status=403)

            db_status_dashboards.edit_custom_status_dashboard(
                conn, times.get_current_timestamp(), org_id, request.data[var_names.url],
                request.data[var_names.dashboard_name], request.data[var_names.dashboard_url],
                request.data[var_names.business_services]
            )

            return Response(_lt.get_label(info.msg_status_dashboard_edited, lang))
        except InvalidRequest as e:
            logging.exception(str(e))
            return Response(_lt.get_label(str(e), lang), status=400)
        except (UnauthorizedRequest, jwt.ExpiredSignatureError, jwt.InvalidSignatureError) as e:
            logging.exception(str(e))
            return Response(_lt.get_label(errors.err_authorization, lang), status=401)
        except Exception as e:
            logging.exception(str(e))
            return Response(_lt.get_label(errors.err_system_error, lang), status=500)
        finally:
            CONN_POOL.put_db_conn(conn)


@api_view(['POST'])
def delete_custom_dashboard(request, conn=None):
    '''
    Create a status dashboard.
    :param request: Http request
    :param conn: db connection
    :return: JSON response
    '''
    if request.method == 'POST':
        lang = request_validator.get_user_language(request)
        expected_fields = [var_names.dashboard_url]
        try:
            conn = CONN_POOL.get_db_conn() if conn is None else conn
            request_validator.validate_fields(request, expected_fields)
            user_id, org_id, user_perm, org_perm = tokenizer.authorize_request(request)

            if not permissions.has_org_permission(org_perm, permissions.ORG_STATUS_DASHBOARDS_CREATE_PERMISSION):
                return Response(_lt.get_label(errors.err_subscription_rights, lang), status=403)
            if not permissions.has_user_permission(user_perm, permissions.USER_STATUS_DASHBOARD_EDIT_PERMISSION):
                return Response(_lt.get_label(errors.err_user_rights, lang), status=403)

            db_status_dashboards.delete_custom_status_dashboard(
                conn, times.get_current_timestamp(), org_id, request.data[var_names.dashboard_url]
            )

            return Response(_lt.get_label(info.msg_status_dashboard_deleted, lang))
        except InvalidRequest as e:
            logging.exception(str(e))
            return Response(_lt.get_label(str(e), lang), status=400)
        except (UnauthorizedRequest, jwt.ExpiredSignatureError, jwt.InvalidSignatureError) as e:
            logging.exception(str(e))
            return Response(_lt.get_label(errors.err_authorization, lang), status=401)
        except Exception as e:
            logging.exception(str(e))
            return Response(_lt.get_label(errors.err_system_error, lang), status=500)
        finally:
            CONN_POOL.put_db_conn(conn)
