# By: Asif Al Shahriar
# This module works with HaloITSM integration data in the database.

from utils import integration_type_names as intt, key_manager, var_names
import datetime
import psycopg2
import logging

def get_haloitsm_accounts(conn, timestamp, organization_id, integration_key=None):
    '''
    Get the list of HaloITSM accounts of an organization.
    :param conn: db connection
    :param timestamp: timestamp when the request was made
    :param organization_id: the organization ID
    :param integration_key: (concealed) integration key of the integration
    :return: (list of dict) -> [{vendor_endpoint_name: full domain, secret_token: API key}, ...]
    :errors: AssertionError, DatabaseError
    '''
    assert isinstance(timestamp, datetime.datetime)
    assert isinstance(organization_id, int)

    query_params = {'timestamp': timestamp, 'org_id': organization_id, 'int_type': intt.haloitsm}
    conditions = []
    if integration_key is not None:
        conditions.append('integration_key = %(integ_key)s')
        query_params['integ_key'] = key_manager.unmask_reference_key(integration_key)

    query = '''
            select vendor_endpoint_name, access_token, secret_token
            from service_integrations as si
            join integration_types as it
                on it.integration_type_id = si.integration_type_id
                    and it.start_date <= %(timestamp)s
                    and it.end_date > %(timestamp)s
            where si.start_timestamp <= %(timestamp)s
                and si.end_timestamp > %(timestamp)s
                and si.organization_id = %(org_id)s
                and it.integration_type = %(int_type)s
                {0};
            '''.format(' and ' + ' and '.join(conditions) if len(conditions) > 0 else '')
    try:
        result = conn.fetch(query, query_params)
        data = []
        for item in result:
            data.append({
                var_names.vendor_endpoint_name: item[0],
                var_names.access_token: item[1],
                var_names.secret_token: item[2]
            })
        logging.info(data)
        return data
    except psycopg2.DatabaseError:
        raise


def update_haloitsm_account(conn, timestamp, organization_id, service_ref_id, integration_key,
                                haloitsm_domain, haloitsm_api_key):
    '''
    Update HaloITSM integration domain and api key. Ensure that an entry for a HaloITSM account integration
    with the given domain exists.
    :param conn: db connection
    :param timestamp: timestamp when this request is being made
    :param organization_id: ID of the organization to check against
    :param service_ref_id: (concealed) reference ID of the service the integration belongs to
    :param integration_key: (concealed) unique key for the integration
    :param haloitsm_domain: domain of the HaloITSM account
    :param haloitsm_api_key: api key to use for the HaloITSM account
    :return: (boolean) True if it exists; False otherwise
    '''
    assert isinstance(timestamp, datetime.datetime)
    assert isinstance(organization_id, int)
    assert isinstance(haloitsm_domain, str)
    assert isinstance(haloitsm_api_key, str)
    unmasked_serv_ref = key_manager.unmask_reference_key(service_ref_id)
    unmasked_integ_key = key_manager.unmask_reference_key(integration_key)

    query = '''
            update service_integrations set vendor_endpoint_name = %(halo_dom)s, secret_token = %(halo_apk)s
            where start_timestamp <= %(timestamp)s
                and end_timestamp > %(timestamp)s
                and organization_id = %(org_id)s
                and integration_key = %(integ_key)s
                and integration_type_id in (
                    select integration_type_id from integration_types
                    where start_date <= %(timestamp)s
                        and end_date > %(timestamp)s
                        and integration_type = %(integ_type)s
                )
                and serviceid in (
                    select serviceid from services
                    where start_timestamp <= %(timestamp)s
                        and end_timestamp > %(timestamp)s
                        and service_ref_id = %(srv_ref)s
                )
            returning vendor_endpoint_name;
            '''
    query_params = {'timestamp': timestamp, 'org_id': organization_id, 'srv_ref': unmasked_serv_ref,
                    'integ_key': unmasked_integ_key, 'integ_type': intt.haloitsm,
                    'halo_dom': haloitsm_domain, 'halo_apk': haloitsm_api_key}
    try:
        result = conn.fetch(query, query_params)
        if len(result) == 0:
            return False
        else:
            return True
    except psycopg2.DatabaseError:
        raise
