# By: Riasat Ullah
# This file contains functions for handling custom integrations.

from utils import constants, helpers, var_names
from validations import string_validator
import re


def get_tc_field_values(payload_map, new_payload):
    '''
    Get the TaskCall required field values from the incoming alert payload using a defined payload map.
    :param payload_map: (dict) map of how TaskCall fields should map to the incoming payload
    :param new_payload: (dict) incoming payload
    :return: (dict) of required fields and their respective values extracted from the incoming payload
    '''
    required_fields = [var_names.title, var_names.description, var_names.status, var_names.urgency_level,
                       var_names.snapshots, var_names.tags, var_names.notes, var_names.dedup_key]
    field_values = dict()
    for key in required_fields:
        if key in payload_map:
            msg = payload_map[key]
            try:
                ext_value = helpers.extract_field_values_from_dict(msg, new_payload)
                field_values[key] = ext_value
            except Exception:
                continue
    return field_values


def is_alert_similar(base_payload, new_payload, group_by_keys):
    '''
    Check if an incoming alert is similar to the alert that created an existing incident.
    :param base_payload: payload of an existing incident
    :param new_payload: payload of the new alert
    :param group_by_keys: (list) of names of the attributes whose values together will be used for equality
    :return: (boolean) True if it is similar; False otherwise
    '''
    match_count = 0
    if group_by_keys is not None:
        for key in group_by_keys:
            try:
                base_key_value = helpers.get_dict_value_from_dotted_key(base_payload, key)
                new_payload_value = helpers.get_dict_value_from_dotted_key(new_payload, key)
                if base_key_value == new_payload_value:
                    match_count += 1
            except Exception:
                break

    if 0 < len(group_by_keys) == match_count:
        return True
    return False


def get_status(status_map, given_value):
    '''
    Get the TaskCall status from the status map and extracted value from the incoming payload.
    :param status_map: (dict) defined status map in the payload
    :param given_value: (str) value extracted from the incoming payload
    :return: (int) urgency level
    '''
    status = constants.open_state
    if given_value is not None:
        for key in status_map:
            status_key_value = status_map[key]
            if not string_validator.is_empty_string(status_key_value):
                status_key_value = [x.strip() for x in status_key_value.split(',')]
                for sts_val in status_key_value:
                    if str(sts_val).lower() == str(given_value).lower():
                        status = key
                        break
    return status


def get_urgency_level(urgency_map, given_value):
    '''
    Get the TaskCall urgency level from the urgency map and extracted value from the incoming payload.
    :param urgency_map: (dict) defined urgency map in the payload
    :param given_value: (str) value extracted from the incoming payload
    :return: (int) urgency level
    '''
    urgency = constants.critical_urgency
    if given_value is not None:
        for key in urgency_map:
            urgency_key_value = urgency_map[key]
            if not string_validator.is_empty_string(urgency_key_value):
                urgency_key_value = [x.strip() for x in urgency_key_value.split(',')]
                for urg_val in urgency_key_value:
                    if str(urg_val).lower() == str(given_value).lower():
                        urgency = int(key)
                        break
    return urgency


def get_snapshots(given_value):
    '''
    Get the snapshots to add to the incident after verifying they are in the correct format.
    :param given_value: the snapshots value extracted from the incoming payload
    :return: (list) of snapshots or None
    '''
    snapshots = []
    if isinstance(given_value, str):
        given_value = [given_value]

    if isinstance(given_value, list):
        snapshots = []
        for item in given_value:
            if string_validator.is_web_url(item):
                snapshots.append(item)

    if len(snapshots) > 0:
        return snapshots
    return None


def is_url_format_valid(url_format, given_value):
    '''
    Validates if the URL format matches if one is defined.
    :param url_format: the regex format of the URL
    :param given_value: the full URL received in the request
    :return: True if the URL format matches; False otherwise
    '''
    if url_format is None or string_validator.is_empty_string(url_format):
        return True
    else:
        if re.match(url_format, given_value):
            return True
        return False
