# By: Riasat Ullah
# This file contains views that are available to the public and
# requires a public token authorization generated by the web app.

from dbqueries import db_accounts, db_routines, db_policies, db_users
from exceptions.user_exceptions import UnauthorizedRequest
from modules import on_call_manager
from rest_framework.decorators import api_view
from rest_framework.response import Response
from translators import label_translator as _lt
from utils import errors, logging, times, tokenizer, var_names
from utils.db_connection import CONN_POOL
from validations import request_validator
import jwt


@api_view(['POST'])
def public_user_on_call_shifts(request, conn=None):
    '''
    Get a user's on-call calendar.
    :param request: Http request
    :param conn: db connection
    :return: Http response -> dict
    '''
    if request.method == 'POST':
        lang = request_validator.get_user_language(request)
        expected_fields = [var_names.preferred_username, var_names.start_date, var_names.end_date]
        try:
            conn = CONN_POOL.get_db_conn() if conn is None else conn
            request_validator.validate_fields(request, expected_fields)
            subdomain, acc_number = tokenizer.verify_public_request(request)
            current_time = times.get_current_timestamp()

            org_id, org_perm = db_accounts.get_org_info_for_public_request(conn, current_time, subdomain, acc_number)
            pref_name = request.data[var_names.preferred_username]
            start_date = times.get_date_from_string(request.data[var_names.start_date])
            end_date = times.get_date_from_string(request.data[var_names.end_date])

            usr_obj = db_users.get_user(
                conn, current_time, keyed_on=var_names.preferred_username, preferred_username=pref_name)[pref_name]
            historical_policy_data = db_policies.get_historical_policies(
                conn, start_date, end_date, org_id, usr_obj.user_id)

            on_call_calendar = on_call_manager.prepare_on_call_calendar(
                historical_policy_data, usr_obj.policy_id, usr_obj.timezone, start_date, end_date)

            details = {
                var_names.display_name: usr_obj.first_name + ' ' + usr_obj.last_name,
                var_names.preferred_username: usr_obj.preferred_username,
                var_names.timezone: usr_obj.timezone,
                var_names.data: on_call_calendar
            }
            return Response(details)
        except LookupError as e:
            logging.info(str(e))
            return Response(_lt.get_label(errors.err_unknown_resource, 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 public_routine_shifts(request, conn=None):
    '''
    Get a routine's calendar.
    :param request: Http request
    :param conn: db connection
    :return: Http response -> dict
    '''
    if request.method == 'POST':
        lang = request_validator.get_user_language(request)
        expected_fields = [var_names.routine_ref_id, var_names.start_date, var_names.end_date]
        try:
            conn = CONN_POOL.get_db_conn() if conn is None else conn
            request_validator.validate_fields(request, expected_fields)
            subdomain, acc_number = tokenizer.verify_public_request(request)
            current_time = times.get_current_timestamp()

            org_id, org_perm = db_accounts.get_org_info_for_public_request(conn, current_time, subdomain, acc_number)
            rou_ref = request.data[var_names.routine_ref_id]
            start_date = times.get_date_from_string(request.data[var_names.start_date])
            end_date = times.get_date_from_string(request.data[var_names.end_date])

            rou_dict = db_routines.get_routines(conn, current_time, org_id, routine_ref_id=rou_ref)
            if len(rou_dict) == 0:
                raise LookupError(errors.err_unknown_resource)

            rou_id = list(rou_dict.keys())[0]
            rou_obj = rou_dict[rou_id]
            historical_rou_data = db_routines.get_historical_routines(conn, start_date, end_date, org_id, rou_id)
            rou_calendar, rou_shifts = on_call_manager.prepare_routine_calendar(
                historical_rou_data, rou_obj.routine_timezone, start_date, end_date)

            details = {
                var_names.display_name: rou_obj.routine_name,
                var_names.routine_ref_id: rou_ref,
                var_names.timezone: rou_obj.routine_timezone,
                var_names.data: rou_calendar
            }
            return Response(details)
        except LookupError as e:
            logging.info(str(e))
            return Response(_lt.get_label(errors.err_unknown_resource, 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)
