# By: Riasat Ullah
# This file contains functions for handling database queries specific to the custom endpoint integration.

from utils import constants, integration_type_names as intt, key_manager, permissions, var_names
from validations import string_validator
import configuration as configs
import datetime
import json
import psycopg2


def get_custom_endpoint_and_headers(conn, timestamp, org_id, integration_key):
    '''
    Get the url and headers of a custom endpoint integrations (including Rundeck).
    The headers are stored under the conditions_map column in the service_integrations table.
    :param conn: db connection
    :param timestamp: timestamp when the request was made
    :param org_id: ID of the organization
    :param integration_key: (concealed) integration key
    :return: (list) of header keys
    '''
    assert isinstance(timestamp, datetime.datetime)
    assert isinstance(org_id, int)
    unmasked_integ_key = key_manager.unmask_reference_key(integration_key)

    query = '''
            select vendor_endpoint, conditions_map from service_integrations
            where start_timestamp <= %(timestamp)s
                and end_timestamp > %(timestamp)s
                and organization_id = %(org_id)s
                and integration_key = %(itg_key)s
                and integration_type_id in (
                    select integration_type_id from integration_types
                    where start_timestamp <= %(timestamp)s
                        and end_timestamp > %(timestamp)s
                        and integration_type = any(%(itg_types)s)
                );
            '''
    query_params = {'timestamp': timestamp, 'org_id': org_id, 'itg_key': unmasked_integ_key,
                    'itg_types': [intt.custom_endpoint, intt.rundeck]}
    try:
        result = conn.fetch(query, query_params)
        data = dict()
        for url_, hdrs_ in result:
            if hdrs_ is None:
                headers = None
            else:
                headers = list(hdrs_.keys())
                headers.sort()

            data = {var_names.vendor_endpoint: url_,
                    var_names.headers: headers}
            break
        return data
    except psycopg2.DatabaseError:
        raise


def reauthorize_custom_endpoint_integration(
        conn, timestamp, organization_id, updated_by, integ_key, vendor_endpoint, secret_token=None, headers=None,
        check_adv_perm=False, has_comp_perm=False, has_team_perm=False
):
    '''
    Reauthorizes a custom endpoint integration.
    :param conn: db connection
    :param timestamp: timestamp when this request is being made
    :param organization_id: ID of the organization
    :param updated_by: user_id of the user who created/updated the details
    :param integ_key: UUID -> the integration key that uniquely identifies this integration
    :param vendor_endpoint: the URL endpoint
    :param secret_token: the authorization token to be sent in the header
    :param headers: (dict) of custom headers to be sent with the webhook
    :param check_adv_perm: (boolean) should advanced permissions be checked
    :param has_comp_perm: (boolean) does the organization have advanced permissions
    :param has_team_perm: (boolean) does the organization have team permissions
    :errors: AssertionError, DatabaseError
    '''
    assert isinstance(timestamp, datetime.datetime)
    assert isinstance(organization_id, int)
    assert isinstance(updated_by, int)
    assert string_validator.is_web_url(vendor_endpoint)
    unmasked_integ_key = key_manager.unmask_reference_key(integ_key)

    if secret_token is not None:
        assert isinstance(secret_token, str)
    if headers is not None:
        assert isinstance(headers, dict)
        headers = json.dumps(headers)

    adv_perm_type = permissions.COMPONENT_ADVANCED_EDIT_PERMISSION

    query = '''
            select reauthorize_custom_endpoint_integration(
                %s, %s, %s, %s::smallint, %s,
                %s, %s, %s, %s,
                %s, %s, %s, %s
            );
            '''
    query_params = (check_adv_perm, has_comp_perm, has_team_perm, configs.service_component_type_id, adv_perm_type,
                    timestamp, constants.end_timestamp, organization_id, unmasked_integ_key,
                    vendor_endpoint, secret_token, headers, updated_by,)
    try:
        conn.execute(query, query_params)
    except psycopg2.DatabaseError:
        raise
