# By: Riasat Ullah
# This file contains views for handling Zoom authorization pages.

from constants import api_paths, label_names as lnm, pages, static_vars, var_names
from django.http import JsonResponse
from django.shortcuts import redirect
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods
from integrations import zoom
from taskcallweb import settings
from translators import label_translator as lt
from utils import helpers, logging
from validations import request_validator
import base64
import json
import requests


@require_http_methods(['GET'])
def authorize_zoom_integration(request):
    '''
    Handles the authorization of the Zoom integration process.
    :param request: Http request
    :return: Http response
    '''
    logging.info(request.GET)
    if request.method == 'GET':
        if 'error' in request.GET:
            if 'error_description' in request.GET:
                err_desc = request.GET['error_description']
            else:
                err_desc = request.GET['error']
            logging.error(err_desc)
            url_to_send_to = pages.conference_bridges_url + '?error=' + err_desc
            return redirect(url_to_send_to)
        elif 'code' not in request.GET and 'state' not in request.GET:
            logging.error('Expected parameters "code" and "state" are missing. Denying access to Zoom integration ' +
                          'authorization. Redirecting to login page.')
            return redirect(pages.login_url)
        else:
            code = request.GET['code']
            state = request.GET['state']

            if not request_validator.user_in_session(request) or \
                (var_names.conference_bridges not in request.session
                 and var_names.state not in request.session[var_names.conference_bridges]
                 and not (var_names.conference_name in request.session[var_names.conference_bridges] or
                          var_names.integration_type in request.session[var_names.conference_bridges]))\
                    and request.session[var_names.conference_bridges][var_names.integration_type]\
                    != static_vars.integ_type_zoom:

                logging.error('Expected service session variables were not found. Denying access ' +
                              'to zoom integration authorization. Redirecting to login page.')
                return redirect(pages.login_url)
            else:
                lang = request_validator.get_user_language(request)
                conf_session = request.session[var_names.conference_bridges]
                failed = True
                if state == conf_session[var_names.state]:
                    try:
                        zoom_creds = zoom.get_zoom_credentials()
                        auth_key = "{}".format(base64.b64encode(
                            bytes("{}:{}".format(
                                zoom_creds[var_names.client_id], zoom_creds[var_names.client_secret]
                            ).encode("utf-8"))).decode("utf-8"))
                        headers = {
                            'Content-Type': 'application/x-www-form-urlencoded',
                            'Authorization': 'Basic ' + auth_key
                        }
                        post_body = {
                            var_names.grant_type: 'authorization_code',
                            var_names.redirect_uri: zoom.get_zoom_to_tc_redirect_uri(),
                            var_names.code: code
                        }

                        # Get Zoom authorization and refresh tokens.
                        oauth_resp = requests.post(zoom.zoom_token_retrieval_path, headers=headers, data=post_body)
                        oauth_data = oauth_resp.json()
                        if oauth_resp.status_code == 200 and 'errorCode' not in oauth_data:
                            access_token = oauth_data[var_names.access_token]
                            refresh_token = oauth_data[var_names.refresh_token]

                            # get the zoom organization ID with the access token
                            zoom_user_resp = requests.get(
                                zoom.zoom_user_path,
                                headers={"Authorization": "Bearer " + access_token, "Accept": "application/json"}
                            )
                            if zoom_user_resp.status_code == 200:
                                zoom_org_id = zoom_user_resp.json()[var_names.account_id]
                                if settings.TEST_MODE:
                                    failed = False
                                else:
                                    final_body = {
                                        var_names.conference_name: conf_session[var_names.conference_name],
                                        var_names.integration_type: static_vars.integ_type_zoom,
                                        var_names.external_id: zoom_org_id,
                                        var_names.external_info: {
                                            var_names.access_token: access_token,
                                            var_names.refresh_token: refresh_token
                                        }
                                    }
                                    final_status, final_output = helpers.post_api_request(
                                        api_paths.conference_bridges_create, final_body, request, lang=lang)
                                    if final_status == 200:
                                        failed = False
                                        del request.session[var_names.conference_bridges]

                    except Exception as e:
                        logging.exception(str(e))

                if failed:
                    logging.exception(lnm.err_verification_failed)
                    return redirect(pages.conference_bridges_url + '?error=' +
                                    lt.get_label(lnm.err_unauthorized_access, lang))
                else:
                    return redirect(pages.conference_bridges_url)


@csrf_exempt
@require_http_methods(['POST'])
def remove_zoom_integration(request):
    '''
    Handles Zoom application uninstallation request.
    :param request: Http request
    :return: JSON response
    '''
    if request.method == 'POST':
        lang = request_validator.get_user_language(request)
        body = json.loads(request.body.decode())
        if var_names.payload in body and var_names.account_id in body[var_names.payload]:
            zoom_account_id = body[var_names.payload][var_names.account_id]

        return JsonResponse(lt.get_label(lnm.msg_success, lang), status=200, safe=False)
