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

from dbqueries import db_tags
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_tag(request, conn=None):
    '''
    Creates a new tag to be used in the organization for contextual searching.
    :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.tag, var_names.description]
        optional_fields = [var_names.policies, var_names.users, var_names.teams, var_names.services]
        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_CONTEXTUAL_SEARCH_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)

            db_tags.create_tag(
                conn, times.get_current_timestamp(), org_id,
                request.data[var_names.tag], request.data[var_names.description],
                tag_policies=request.data[var_names.policies] if var_names.policies in request.data else None,
                tag_users=request.data[var_names.users] if var_names.users in request.data else None,
                tag_teams=request.data[var_names.teams] if var_names.teams in request.data else None,
                tag_services=request.data[var_names.services] if var_names.services in request.data else None
            )

            return Response(_lt.get_label(info.msg_tag_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_tag(request, conn=None):
    '''
    Edits an existing tag.
    :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.tag, var_names.description]
        optional_fields = [var_names.policies, var_names.users, var_names.teams, var_names.services]
        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_CONTEXTUAL_SEARCH_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)

            db_tags.edit_tag(
                conn, times.get_current_timestamp(), org_id,
                request.data[var_names.tag], request.data[var_names.description],
                tag_policies=request.data[var_names.policies] if var_names.policies in request.data else None,
                tag_users=request.data[var_names.users] if var_names.users in request.data else None,
                tag_teams=request.data[var_names.teams] if var_names.teams in request.data else None,
                tag_services=request.data[var_names.services] if var_names.services in request.data else None
            )

            return Response(_lt.get_label(info.msg_tag_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_tag(request, conn=None):
    '''
    Deletes a tag.
    :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.tag]
        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_CONTEXTUAL_SEARCH_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)

            db_tags.delete_tag(conn, times.get_current_timestamp(), org_id, request.data[var_names.tag])

            return Response(_lt.get_label(info.msg_tag_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)


@api_view(['POST'])
def update_component_tags(request, conn=None):
    '''
    Update the tags associated to a component.
    :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.tags]
        optional_fields = [var_names.policy_ref_id, var_names.preferred_username, var_names.team_ref_id,
                           var_names.service_ref_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_CONTEXTUAL_SEARCH_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)

            db_tags.save_component_tags(
                conn, times.get_current_timestamp(), org_id, request.data[var_names.tags],
                policy_ref_id=request.data[var_names.policy_ref_id]
                if var_names.policy_ref_id in request.data else None,
                preferred_username=request.data[var_names.preferred_username]
                if var_names.preferred_username in request.data else None,
                team_ref_id=request.data[var_names.team_ref_id] if var_names.team_ref_id in request.data else None,
                service_ref_id=request.data[var_names.service_ref_id]
                if var_names.service_ref_id in request.data else None
            )

            return Response(_lt.get_label(info.msg_success, lang))
        except (InvalidRequest, LookupError) 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)
