# By: Riasat Ullah
# This file contains general monitor check related views.

from data_syncers import syncer_checks
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 CACHE_CLIENT, CONN_POOL
from validations import request_validator
import jwt


@api_view(['POST'])
def create_check(request, conn=None, cache=None):
    '''
    Create a monitor check.
    :param request: Http request
    :param conn: db connection
    :param cache: cache client
    :return: Http response
    '''
    if request.method == 'POST':
        lang = request_validator.get_user_language(request)
        expected_fields = [var_names.check_type, var_names.check_name, var_names.description, var_names.ping_type,
                           var_names.url, var_names.email, var_names.interval, var_names.grace_period,
                           var_names.service_ref_id, var_names.task_title, var_names.text_msg, var_names.urgency_level]
        optional_fields = [var_names.check_ref_id, var_names.tags, var_names.ip_address, var_names.email_from,
                           var_names.packet_sizes, var_names.degraded_timeout, var_names.fail_timeout,
                           var_names.check_ssl_expiry, var_names.port, var_names.additional_info]
        try:
            conn = CONN_POOL.get_db_conn() if conn is None else conn
            cache = CACHE_CLIENT if cache is None else cache
            request_validator.validate_fields(request, expected_fields, optional_fields)
            user_id, org_id, user_perm, org_perm = tokenizer.authorize_request(request)

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

            req_check_ref_id = request.data[var_names.check_ref_id] if var_names.check_ref_id in request.data else None
            do_adv_check, do_comp_check, do_team_check = permissions.get_user_advanced_check_status(user_perm, org_perm)

            check_ref_id = syncer_checks.create_check(
                conn, cache, times.get_current_timestamp(), org_id, user_id, req_check_ref_id,
                request.data[var_names.check_type], request.data[var_names.check_name],
                request.data[var_names.description], request.data[var_names.ping_type],
                request.data[var_names.url], request.data[var_names.email],
                request.data[var_names.interval], request.data[var_names.grace_period],
                request.data[var_names.service_ref_id], request.data[var_names.task_title],
                request.data[var_names.text_msg], request.data[var_names.urgency_level],
                tags=request.data[var_names.tags] if var_names.tags in request.data else None,
                ip_whitelist=request.data[var_names.ip_address] if var_names.ip_address in request.data else None,
                email_whitelist=request.data[var_names.email_from] if var_names.email_from in request.data else None,
                packet_sizes=request.data[var_names.packet_sizes] if var_names.packet_sizes in request.data else None,
                degraded_timeout=request.data[var_names.degraded_timeout]
                if var_names.degraded_timeout in request.data else None,
                fail_timeout=request.data[var_names.fail_timeout] if var_names.fail_timeout in request.data else None,
                check_ssl_expiry=request.data[var_names.check_ssl_expiry]
                if var_names.check_ssl_expiry in request.data else None,
                ping_port=request.data[var_names.port] if var_names.port in request.data else None,
                additional_info=request.data[var_names.additional_info]
                if var_names.additional_info in request.data else None,
                check_adv_perm=do_adv_check, has_comp_perm=do_comp_check, has_team_perm=do_team_check
            )
            return Response({var_names.check_ref_id: check_ref_id})
        except InvalidRequest as e:
            logging.exception(str(e))
            return Response(_lt.get_label(str(e), lang), status=400)
        except PermissionError as e:
            logging.exception(str(e))
            return Response(_lt.get_label(str(e), lang), status=403)
        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_check(request, conn=None, cache=None):
    '''
    Edit a monitor check.
    :param request: Http request
    :param conn: db connection
    :param cache: cache client
    :return: Http response
    '''
    if request.method == 'POST':
        lang = request_validator.get_user_language(request)
        expected_fields = [var_names.check_ref_id, var_names.check_type, var_names.check_name, var_names.description,
                           var_names.ping_type, var_names.url, var_names.email, var_names.interval,
                           var_names.grace_period, var_names.service_ref_id, var_names.task_title, var_names.text_msg,
                           var_names.urgency_level]
        optional_fields = [var_names.tags, var_names.ip_address, var_names.email_from,
                           var_names.packet_sizes, var_names.degraded_timeout, var_names.fail_timeout,
                           var_names.check_ssl_expiry, var_names.port, var_names.additional_info]
        try:
            conn = CONN_POOL.get_db_conn() if conn is None else conn
            cache = CACHE_CLIENT if cache is None else cache
            request_validator.validate_fields(request, expected_fields, optional_fields)
            user_id, org_id, user_perm, org_perm = tokenizer.authorize_request(request)

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

            do_adv_check, do_comp_check, do_team_check = permissions.get_user_advanced_check_status(user_perm, org_perm)

            syncer_checks.edit_check(
                conn, cache, times.get_current_timestamp(), org_id, user_id, request.data[var_names.check_ref_id],
                request.data[var_names.check_type], request.data[var_names.check_name],
                request.data[var_names.description], request.data[var_names.ping_type],
                request.data[var_names.url], request.data[var_names.email],
                request.data[var_names.interval], request.data[var_names.grace_period],
                request.data[var_names.service_ref_id], request.data[var_names.task_title],
                request.data[var_names.text_msg], request.data[var_names.urgency_level],
                tags=request.data[var_names.tags] if var_names.tags in request.data else None,
                ip_whitelist=request.data[var_names.ip_address] if var_names.ip_address in request.data else None,
                email_whitelist=request.data[var_names.email_from] if var_names.email_from in request.data else None,
                packet_sizes=request.data[var_names.packet_sizes] if var_names.packet_sizes in request.data else None,
                degraded_timeout=request.data[var_names.degraded_timeout]
                if var_names.degraded_timeout in request.data else None,
                fail_timeout=request.data[var_names.fail_timeout] if var_names.fail_timeout in request.data else None,
                check_ssl_expiry=request.data[var_names.check_ssl_expiry]
                if var_names.check_ssl_expiry in request.data else None,
                ping_port=request.data[var_names.port] if var_names.port in request.data else None,
                additional_info=request.data[var_names.additional_info]
                if var_names.additional_info in request.data else None,
                check_adv_perm=do_adv_check, has_comp_perm=do_comp_check, has_team_perm=do_team_check
            )
            return Response(_lt.get_label(info.msg_check_edited, lang))
        except InvalidRequest as e:
            logging.exception(str(e))
            return Response(_lt.get_label(str(e), lang), status=400)
        except PermissionError as e:
            logging.exception(str(e))
            return Response(_lt.get_label(str(e), lang), status=403)
        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_check(request, conn=None, cache=None):
    '''
    Delete a monitor check.
    :param request: Http request
    :param conn: db connection
    :param cache: cache client
    :return: Http response
    '''
    if request.method == 'POST':
        lang = request_validator.get_user_language(request)
        expected_fields = [var_names.check_ref_id, var_names.check_type]
        try:
            conn = CONN_POOL.get_db_conn() if conn is None else conn
            cache = CACHE_CLIENT if cache is None else cache
            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_CHECKS_BASIC_PERMISSION):
                return Response(_lt.get_label(errors.err_subscription_rights, lang), status=403)
            if not permissions.can_user_edit_components(user_perm, org_perm):
                return Response(_lt.get_label(errors.err_user_rights, lang), status=403)

            check_ref_id = request.data[var_names.check_ref_id]
            check_type = request.data[var_names.check_type]
            do_adv_check, do_comp_check, do_team_check = permissions.get_user_advanced_check_status(user_perm, org_perm)

            syncer_checks.delete_check(
                conn, cache, times.get_current_timestamp(), org_id, user_id, check_ref_id, check_type,
                check_adv_perm=do_adv_check, has_comp_perm=do_comp_check, has_team_perm=do_team_check
            )
            return Response(_lt.get_label(info.msg_check_deleted, lang))
        except InvalidRequest as e:
            logging.exception(str(e))
            return Response(_lt.get_label(str(e), lang), status=400)
        except PermissionError as e:
            logging.exception(str(e))
            return Response(_lt.get_label(str(e), lang), status=403)
        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 enable_check(request, conn=None, cache=None):
    '''
    Enable/disable a monitor check.
    :param request: Http request
    :param conn: db connection
    :param cache: cache client
    :return: Http response
    '''
    if request.method == 'POST':
        lang = request_validator.get_user_language(request)
        logging.info(request.data)
        expected_fields = [var_names.check_ref_id, var_names.check_type, var_names.is_enabled]
        try:
            conn = CONN_POOL.get_db_conn() if conn is None else conn
            cache = CACHE_CLIENT if cache is None else cache
            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_CHECKS_BASIC_PERMISSION):
                return Response(_lt.get_label(errors.err_subscription_rights, lang), status=403)
            if not permissions.can_user_edit_components(user_perm, org_perm):
                return Response(_lt.get_label(errors.err_user_rights, lang), status=403)

            check_ref_id = request.data[var_names.check_ref_id]
            check_type = request.data[var_names.check_type]
            to_enable = request.data[var_names.is_enabled]

            do_adv_check, do_comp_check, do_team_check = permissions.get_user_advanced_check_status(user_perm, org_perm)
            syncer_checks.enable_check(
                conn, cache, times.get_current_timestamp(), org_id, user_id, check_ref_id, check_type, to_enable,
                check_adv_perm=do_adv_check, has_comp_perm=do_comp_check, has_team_perm=do_team_check
            )
            msg = info.msg_check_enabled if to_enable else info.msg_check_disabled
            return Response(_lt.get_label(msg, lang))
        except InvalidRequest as e:
            logging.exception(str(e))
            return Response(_lt.get_label(str(e), lang), status=400)
        except PermissionError as e:
            logging.exception(str(e))
            return Response(_lt.get_label(str(e), lang), status=403)
        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)
