# By: Riasat Ullah
# This module works with Microsoft Teams integration data in the database.

from utils import integration_type_names, key_manager, var_names
import datetime
import psycopg2


def get_microsoft_teams_integration_details(conn, timestamp, external_id, ms_teams_channel_id):
    '''
    Get the ID of the service MS Teams channel is integrated with.
    :param conn: db connection
    :param timestamp: timestamp when this request is being made
    :param external_id: MS Teams tenant ID
    :param ms_teams_channel_id: the MS Teams channel ID
    :return: (tuple) -> (organization ID, service ID, integration ID, external info)
    '''
    assert isinstance(timestamp, datetime.datetime)
    assert isinstance(external_id, str)
    assert isinstance(ms_teams_channel_id, str)

    query = '''
            select organization_id, serviceid, integration_id, oitd.details
            from service_integrations as sint
            join organization_integration_type_details as oitd using(organization_id, integration_type_id)
            where sint.start_timestamp <= %(timestamp)s
                and sint.end_timestamp > %(timestamp)s
                and sint.additional_info->>'channel_id' = %(chn_id)s
                and sint.integration_type_id in (
                    select integration_type_id from integration_types
                    where start_date <= %(timestamp)s
                        and end_date > %(timestamp)s
                        and integration_type = %(ms_teams_type)s
                )
                and oitd.start_timestamp <= %(timestamp)s
                and oitd.end_timestamp > %(timestamp)s
                and oitd.external_id = %(ext_id)s;
            '''
    query_params = {'timestamp': timestamp, 'ext_id': external_id, 'chn_id': ms_teams_channel_id,
                    'ms_teams_type': integration_type_names.microsoft_teams}
    try:
        result = conn.fetch(query, query_params)
        for org_id, serv_id, integ_id, ext_info in result:
            return org_id, serv_id, integ_id, ext_info

        return None, None, None, None
    except psycopg2.DatabaseError:
        raise


def get_org_microsoft_teams_integrations(conn, timestamp, organization_id, integration_key=None):
    '''
    Get the basic details of the Microsoft Teams integrations in an organization.
    :param conn: db connection
    :param timestamp: timestamp when this request is being made
    :param organization_id: ID of the organization to check for
    :param integration_key: (concealed) integration key
    :return: (list of dict) -> [{service_name: , integration_name: , integration_key: (concealed)}, ...]
    '''
    assert isinstance(timestamp, datetime.datetime)
    assert isinstance(organization_id, int)

    query_params = {'timestamp': timestamp, 'org_id': organization_id,
                    'ms_teams_integ': integration_type_names.microsoft_teams}
    conditions = []
    if integration_key is not None:
        unmasked_integ_key = key_manager.unmask_reference_key(integration_key)
        conditions.append(" sint.integration_key = %(integ_key)s ")
        query_params['integ_key'] = unmasked_integ_key

    query = '''
            select srv.service_name, sint.integration_name, sint.integration_key, oitd.details
            from service_integrations as sint
            join services as srv using(serviceid)
            join organization_integration_type_details as oitd
                on sint.additional_info ->> 'tenant_id' = oitd.external_id
            where srv.start_timestamp <= %(timestamp)s
                and srv.end_timestamp > %(timestamp)s
                and sint.start_timestamp <= %(timestamp)s
                and sint.end_timestamp > %(timestamp)s
                and sint.organization_id = %(org_id)s
                and sint.integration_type_id in (
                    select integration_type_id
                    from integration_types
                    where start_date <= %(timestamp)s
                        and end_date > %(timestamp)s
                        and integration_type = %(ms_teams_integ)s
                )
                and oitd.start_timestamp <= %(timestamp)s
                and oitd.end_timestamp > %(timestamp)s
                {0};
            '''.format(' and ' + ' and '.join(conditions) if len(conditions) > 0 else '')
    try:
        result = conn.fetch(query, query_params)
        data = []
        for srv_name, integ_name, integ_key, addn_info in result:
            data.append({
                var_names.service_name: srv_name,
                var_names.integration_name: integ_name,
                var_names.integration_key: key_manager.conceal_reference_key(integ_key),
                var_names.additional_info: addn_info
            })
        return data
    except psycopg2.DatabaseError:
        raise
