# By: Riasat Ullah
# This file contains code for handling Slack authorization pages.

from constants import api_paths, label_names as lnm, static_vars, url_paths, var_names
from django.shortcuts import redirect
from django.views.decorators.http import require_http_methods
from integrations import slack
from taskcallweb import settings
from utils import cdn_enablers, helpers, logging, s3
from validations import request_validator


@require_http_methods(['GET'])
def redirect_to_slack_authorization_page(request):
    '''
    Redirects to the Slack authorization page.
    :param request: Http request
    :return: Http response
    '''
    if request.method == 'GET':
        srv_ref = request.session[var_names.services][var_names.service_ref_id]
        return redirect(slack.get_slack_oauth_path(srv_ref))


@require_http_methods(['GET'])
def authorize_slack_integration(request):
    '''
    Handles the authorization of the Slack integration process.
    :param request: Http request
    :return: Http response
    '''
    if request.method == 'GET':
        lang = request_validator.get_user_language(request)
        region = request_validator.get_host_region(request)

        if settings.REGION != region and region == static_vars.aws_us_ohio:
            if 'code' in request.GET and 'state' in request.GET:
                code = request.GET['code']
                state = request.GET['state']
                rdr_url = slack.get_web_path_us_tc_slack_authorization(code, state)
                return redirect(rdr_url)

        if var_names.services in request.session and var_names.service_ref_id in request.session[var_names.services]:
            integ_details = request.session[var_names.services]
            serv_ref_id = integ_details[var_names.service_ref_id]

            if 'error' in request.GET:
                logging.error = request.GET['error'] + ' - Slack request authorization failed'
            else:
                try:
                    if 'state' not in request.GET:
                        logging.error('State parameter was not received from Slack')

                    elif request.GET['state'] == serv_ref_id:

                        slack_creds = s3.read_json(slack.slack_s3_bucket, slack.slack_s3_key)
                        request_redirect_uri = slack.get_slack_tc_redirect_path()

                        post_body = {
                            'code': request.GET['code'],
                            'client_id': slack_creds[slack.str_slack_client_id],
                            'client_secret': slack_creds[slack.str_slack_client_secret],
                            'redirect_uri': request_redirect_uri
                        }

                        status, data = helpers.post_api_request(slack.slack_access_token_path, post_body,
                                                                content_type=static_vars.content_type_url_encoded)

                        if status == 200 and 'error' not in data:
                            webhook_details = data['incoming_webhook']
                            slack_access_token = data['access_token']
                            slack_team_id = data['team']['id']
                            slack_team_name = data['team']['name']
                            slack_channel_id = webhook_details['channel_id']

                            integ_details = request.session[var_names.services]
                            post_body = {
                                var_names.service_ref_id: serv_ref_id,
                                var_names.integration_type: integ_details[var_names.integration_type],
                                var_names.integration_name: integ_details[var_names.integration_name],
                                var_names.access_token: slack_access_token,
                                var_names.vendor_endpoint: webhook_details['url'],
                                var_names.vendor_endpoint_name: webhook_details['channel'],
                                var_names.additional_info: {
                                    var_names.team_id: slack_team_id,
                                    var_names.team_name: slack_team_name,
                                    var_names.channel_id: slack_channel_id,
                                    var_names.channel: webhook_details['channel']
                                },
                                var_names.external_id: slack_team_id,
                                var_names.external_info: {
                                    var_names.team_id: slack_team_id,
                                    var_names.team_name: slack_team_name
                                }
                            }

                            status, output = helpers.post_api_request(api_paths.services_integrations_add, post_body,
                                                                      request, lang=lang)
                            if status == 200:
                                # If US region, combine Slack team id and channel id in a key and store it in s3.
                                # It will be used as a cache key to identify the region incoming requests should be
                                # forwarded to.
                                if settings.REGION == static_vars.aws_us_ohio:
                                    cache_key = cdn_enablers.create_cdn_cache_key(
                                        static_vars.integ_type_slack, slack_team_id, slack_channel_id
                                    )
                                    if cache_key is not None:
                                        cdn_enablers.update_external_account_maps_file(
                                            static_vars.integ_type_slack, cache_key)

                                logging.info(lnm.msg_success)
                            else:
                                logging.info(lnm.err_processing_failed)
                        else:
                            logging.error(lnm.err_processing_failed)
                            logging.error(data['error'])
                    else:
                        logging.error('Slack integration - request states do not match. Aborting process.')
                except Exception as e:
                    logging.exception(str(e))
                finally:
                    if var_names.services in request.session:
                        del request.session[var_names.services]

                    return redirect(url_paths.configurations_services + '/' + serv_ref_id)
        else:
            return redirect(url_paths.configurations_services)
