# By: Riasat Ullah
# This file contains functions related to external people views.

from dbqueries.itsm import db_groups, db_people
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 create_group(request, conn=None):
    '''
    Create a new group.
    :param request: HttpRequest
    :param conn: db connection
    :return: HttpResponse -> str
    '''
    if request.method == 'POST':
        lang = request_validator.get_user_language(request)
        expected_fields = [var_names.group_name, var_names.description, var_names.group_type]
        optional_fields = [var_names.sla_response, var_names.sla_resolution, var_names.internal_id, var_names.people]
        try:
            conn = CONN_POOL.get_db_conn() if conn is None else conn
            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_GROUPS_PERMISSION):
                return Response(_lt.get_label(errors.err_subscription_rights, lang), status=403)
            if not permissions.has_user_permission(user_perm, permissions.USER_COMPONENTS_EDIT_PERMISSION):
                return Response(_lt.get_label(errors.err_user_rights, lang), status=403)

            ref_id = db_groups.create_group(
                conn, times.get_current_timestamp(), org_id, request.data[var_names.group_name],
                request.data[var_names.description], request.data[var_names.group_type],
                sla_response=request.data[var_names.sla_response] if var_names.sla_response in request.data else None,
                sla_resolution=request.data[var_names.sla_resolution]
                if var_names.sla_resolution in request.data else None,
                internal_id=request.data[var_names.internal_id] if var_names.internal_id in request.data else None,
                people_ref_ids=request.data[var_names.people] if var_names.people in request.data else None
            )
            return Response(ref_id)
        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_group(request, conn=None):
    '''
    Edit a group.
    :param request: HttpRequest
    :param conn: db connection
    :return: HttpResponse -> str
    '''
    if request.method == 'POST':
        lang = request_validator.get_user_language(request)
        expected_fields = [var_names.group_ref_id, var_names.group_name, var_names.description, var_names.group_type]
        optional_fields = [var_names.sla_response, var_names.sla_resolution, var_names.internal_id]
        try:
            conn = CONN_POOL.get_db_conn() if conn is None else conn
            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_GROUPS_PERMISSION):
                return Response(_lt.get_label(errors.err_subscription_rights, lang), status=403)
            if not permissions.has_user_permission(user_perm, permissions.USER_COMPONENTS_EDIT_PERMISSION):
                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)
            db_groups.edit_group(
                conn, times.get_current_timestamp(), org_id, user_id,
                request.data[var_names.group_ref_id],
                request.data[var_names.group_name],
                request.data[var_names.description],
                request.data[var_names.group_type],
                sla_response=request.data[var_names.sla_response] if var_names.sla_response in request.data else None,
                sla_resolution=request.data[var_names.sla_resolution]
                if var_names.sla_resolution in request.data else None,
                internal_id=request.data[var_names.internal_id] if var_names.internal_id 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_group_edited, lang))
        except PermissionError as e:
            logging.exception(str(e))
            return Response(_lt.get_label(str(e), lang), status=403)
        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 add_group_people(request, conn=None):
    '''
    Add people to the group.
    :param request: HttpRequest
    :param conn: db connection
    :return: HttpResponse -> str
    '''
    if request.method == 'POST':
        lang = request_validator.get_user_language(request)
        expected_fields = [var_names.group_ref_id, var_names.people]
        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_GROUPS_PERMISSION):
                return Response(_lt.get_label(errors.err_subscription_rights, lang), status=403)
            if not permissions.has_user_permission(user_perm, permissions.USER_COMPONENTS_EDIT_PERMISSION):
                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)
            db_groups.add_group_people(
                conn, times.get_current_timestamp(), org_id, user_id, request.data[var_names.group_ref_id],
                request.data[var_names.people], 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_group_people_added, lang))
        except PermissionError as e:
            logging.exception(str(e))
            return Response(_lt.get_label(str(e), lang), status=403)
        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_group_people(request, conn=None):
    '''
    Delete people from the group.
    :param request: HttpRequest
    :param conn: db connection
    :return: HttpResponse -> str
    '''
    if request.method == 'POST':
        lang = request_validator.get_user_language(request)
        expected_fields = [var_names.group_ref_id, var_names.people]
        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_GROUPS_PERMISSION):
                return Response(_lt.get_label(errors.err_subscription_rights, lang), status=403)
            if not permissions.has_user_permission(user_perm, permissions.USER_COMPONENTS_EDIT_PERMISSION):
                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)
            db_groups.delete_group_people(
                conn, times.get_current_timestamp(), org_id, user_id, request.data[var_names.group_ref_id],
                request.data[var_names.people], 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_group_people_deleted, lang))
        except PermissionError as e:
            logging.exception(str(e))
            return Response(_lt.get_label(str(e), lang), status=403)
        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_group(request, conn=None):
    '''
    Delete a group.
    :param request: HttpRequest
    :param conn: db connection
    :return: HttpResponse -> str
    '''
    if request.method == 'POST':
        lang = request_validator.get_user_language(request)
        expected_fields = [var_names.group_ref_id, var_names.to_delete_people]
        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_GROUPS_PERMISSION):
                return Response(_lt.get_label(errors.err_subscription_rights, lang), status=403)
            if not permissions.has_user_permission(user_perm, permissions.USER_COMPONENTS_EDIT_PERMISSION):
                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)
            db_groups.delete_group(
                conn, times.get_current_timestamp(), org_id, user_id, request.data[var_names.group_ref_id],
                to_delete_people=request.data[var_names.to_delete_people], 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_group_deleted, lang))
        except PermissionError as e:
            logging.exception(str(e))
            return Response(_lt.get_label(str(e), lang), status=403)
        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 list_groups(request, conn=None):
    '''
    List the groups of an organization.
    :param request: HttpRequest
    :param conn: db connection
    :return: HttpResponse -> str
    '''
    if request.method == 'POST':
        lang = request_validator.get_user_language(request)
        try:
            conn = CONN_POOL.get_db_conn() if conn is None else conn
            request_validator.validate_fields(request, [])
            user_id, org_id, user_perm, org_perm = tokenizer.authorize_request(request)

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

            do_adv_check = permissions.get_user_advanced_check_status(user_perm, org_perm)[0]

            groups_list = db_groups.list_groups(conn, times.get_current_timestamp(), org_id, user_id,
                                                check_adv_perm=do_adv_check)
            return Response(groups_list)
        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 get_group_details(request, conn=None):
    '''
    Get the details of a group.
    :param request: HttpRequest
    :param conn: db connection
    :return: HttpResponse -> str
    '''
    if request.method == 'POST':
        lang = request_validator.get_user_language(request)
        expected_fields = [var_names.group_ref_id]
        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_GROUPS_PERMISSION):
                return Response(_lt.get_label(errors.err_subscription_rights, lang), status=403)
            if not permissions.has_user_permission(user_perm, permissions.USER_COMPONENTS_VIEW_PERMISSION):
                return Response(_lt.get_label(errors.err_user_rights, lang), status=403)

            do_adv_check = permissions.get_user_advanced_check_status(user_perm, org_perm)[0]
            group_details = db_groups.get_group_details(
                conn, times.get_current_timestamp(), org_id, user_id, request.data[var_names.group_ref_id],
                check_adv_perm=do_adv_check
            )
            return Response(group_details)
        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 get_group_people(request, conn=None):
    '''
    Get the details of a group.
    :param request: HttpRequest
    :param conn: db connection
    :return: HttpResponse -> str
    '''
    if request.method == 'POST':
        lang = request_validator.get_user_language(request)
        expected_fields = [var_names.group_ref_id]
        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_GROUPS_PERMISSION):
                return Response(_lt.get_label(errors.err_subscription_rights, lang), status=403)
            if not permissions.has_user_permission(user_perm, permissions.USER_COMPONENTS_VIEW_PERMISSION):
                return Response(_lt.get_label(errors.err_user_rights, lang), status=403)

            do_adv_check = permissions.get_user_advanced_check_status(user_perm, org_perm)[0]
            grp_ppl_list = db_people.list_people(
                conn, times.get_current_timestamp(), org_id, user_id,
                group_ref_id=request.data[var_names.group_ref_id], check_adv_perm=do_adv_check
            )
            return Response(grp_ppl_list)
        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)
