# By: Asif Al Shahriar
# This file contains code for handling HaloITSM integration related views.
import logging

from constants import api_paths, label_names as lnm, var_names
from django.http import JsonResponse
from django.views.decorators.http import require_http_methods
from integrations import freshservice, haloitsm , datadog
from taskcallweb import settings
from translators import label_translator as lt
from utils import helpers
from validations import request_validator
import boto3
import json
import requests


@require_http_methods(['POST'])
def get_haloitsm_account_info(request):
    '''
    Get the domain and api key of the HaloITSM account associated to an integration.
    This will be displayed on the HaloITSM integration modal.
    :param request: Http request
    :return: JSON response
    '''
    if request.method == 'POST':
        lang = request_validator.get_user_language(request)
        if request_validator.user_in_session(request):
            body = json.loads(request.body.decode())
            if settings.TEST_MODE:
                return JsonResponse([{var_names.vendor_endpoint_name: 'taskcallapp.haloitsm.com',
                                      var_names.secret_token: 'api_key_xx'}], safe=False)
            else:
                status, output = helpers.post_api_request(api_paths.integrations_halo_itsm_account, body,
                                                          request, lang=lang)
                return JsonResponse(output, status=status, safe=False)
        else:
            return JsonResponse(lt.get_label(lnm.err_unauthorized_access, lang), status=401, safe=False)


@require_http_methods(['POST'])
def update_haloitsm_account_info(request):
    '''
    Updates the HaloITSM domain and api key stored for a HaloITSM integration.
    :param request: Http request
    :return: Http response
    '''
    if request.method == 'POST':
        lang = request_validator.get_user_language(request)
        if request_validator.user_in_session(request):
            body = json.loads(request.body.decode())
            if settings.TEST_MODE:
                return JsonResponse('Success', safe=False)
            else:
                status, output = helpers.post_api_request(api_paths.integrations_halo_itsm_account_update, body,
                                                          request, lang=lang)
                return JsonResponse(output, status=status, safe=False)
        else:
            return JsonResponse(lt.get_label(lnm.err_unauthorized_access, lang), status=401, safe=False)


@require_http_methods(['POST'])
def get_haloitsm_meta_data(request):
    '''
    Get the ticket types allowed on a HaloITSM account.
    This will be displayed on the HaloITSM integration modal.
    :param request: Http request
    :return: JSON response
    '''
    if request.method == 'POST':
        lang = request_validator.get_user_language(request)
        if request_validator.user_in_session(request):
            body = json.loads(request.body.decode())
            if settings.TEST_MODE:
                return JsonResponse({
                    var_names.ticket_type: [
                        ['Case', 'Case'], ['Incident', 'Incident'], ['Issue', 'Issue'],
                        ['Major Incident', 'Major Incident'], ['Query', 'Query'], ['Request', 'Request'],
                        ['Service Request', 'Service Request']
                    ],
                    var_names.workspace: [['IT', 2]]
                }, safe=False)
            else:
                resp = requests.get(haloitsm.haloitsm_ticket_types_path.format(
                    body[var_names.domain]), headers={
                    'Authorization': f'Bearer {body[var_names.access_token]}',
                    'Content-Type': 'application/json' })
                status = resp.status_code
                output = resp.json()
                # output is a list of dictionaries, so we will extract ticket types as id and name
                if status == 200:
                    ticket_types = []
                    for tt in output:
                        ticket_types.append([tt['name'], tt['id']])
                    output = {var_names.ticket_type: ticket_types}
                else :
                    logging.error(output)
                # now we will fetch the statuses
                resp_sts = requests.get(haloitsm.haloitsm_statuses_path.format(
                    body[var_names.domain]), headers={
                    'Authorization': f'Bearer {body[var_names.access_token]}',  
                    'Content-Type': 'application/json' })
                status_sts = resp_sts.status_code
                output_sts = resp_sts.json()
                if status_sts == 200:
                    statuses = []
                    for sts in output_sts:
                        statuses.append([sts['name'], sts['id']])
                    output[var_names.status] = statuses
                else:
                    logging.error(output_sts)
                return JsonResponse(output, status=200, safe=False)
        else:
            return JsonResponse(lt.get_label(lnm.err_unauthorized_access, lang), status=401, safe=False)


@require_http_methods(['POST'])
def authorize_haloitsm_integration(request):
    '''
    Handles the authorization of the HaloITSM integration process.
    :param request: Http request
    :return: Http response
    '''
    if request.method == 'POST':
        lang = request_validator.get_user_language(request)
        logging.info(request.body)
        #prepare the post body for the token request
        body = json.loads(request.body.decode())
    
        post_body = {
            'client_id': body[var_names.client_id],
            'client_secret': body[var_names.client_secret],
            'grant_type': 'client_credentials'
        }
        # so now the request is complete and  we will send the post request to get the token
        resp = requests.post(haloitsm.haloitsm_access_token_path.format(
            body[var_names.domain]), data=post_body)
        status = resp.status_code
        data = resp.json()
        logging.info('HaloITSM authorization response: ' + str(data))
        if status == 200 and 'error' not in data:
            return JsonResponse({
                var_names.access_token: data['access_token'],
                var_names.token_type: data['token_type'],
                var_names.expires_in: data['expires_in']
            }, status=200, safe=False)
        else:
            logging.error('HaloITSM authorization failed: ' + str(data))
            return JsonResponse(lt.get_label(lnm.err_unauthorized_access, lang), status=401, safe=False)
        

@require_http_methods(['GET'])
def get_haloitsm_ticket_types(request):
    '''
    Get the ticket types from HaloITSM account.
    :param request: Http request
    :return: JSON response
    '''
    if request.method == 'GET':
        lang = request_validator.get_user_language(request)
        if request_validator.user_in_session(request):
            creds = haloitsm.get_haloitsm_credentials()
            access_token = creds.get('access_token')
            domain = creds.get('domain')
            headers = {
                'Authorization': f'Bearer {access_token}',
                'Content-Type': 'application/json'
            }
            resp = requests.get(haloitsm.haloitsm_ticket_types_path.format(domain), headers=headers)
            status = resp.status_code
            data = resp.json()
            ticket_types = []
            if status == 200:
                for tt in data:
                    ticket_types.append([tt['name'], tt['id']])
            else:
                logging.error('Error fetching HaloITSM ticket types: ' + str(data))
            return JsonResponse({var_names.ticket_type: ticket_types}, status=200, safe=False)
        else:
            return JsonResponse(lt.get_label(lnm.err_unauthorized_access, lang), status=401, safe=False)