
from .juggler import alert_key_from_juggler_tags
from .juggler import alert_is_users_from_juggler_tags
from .juggler import extract_phone_times
from .juggler import extract_flaps

from .golovan import alert_key_from_name

from .formats import GolovanInput

from .dm import alert_keys_from_conf
from .dm import should_have_juggler
from .dm import logins_from_conf
from .dm import is_users_from_conf
from .dm import ring_times_from_conf
from .dm import flaps_from_conf
from .dm import SIGNALS

from .alerts import compare_limits
from .alerts import limits_conf2yasm


def check_alerts(present, need, is_meta):
    """
    :param present: alerts from golovan
    :param need: alerts from dm conf
    :return:
    """
    need_sigks = alert_keys_from_conf(need, is_meta=is_meta)
    # present_sigas = [ga['name'] for ga in present]
    actual_sigks = []
    exceeding_sigks = []
    absent_sigks = []
    mismatch_limits_sigks = set()
    for ga in present:
        skey = alert_key_from_name(ga['name'])
        if skey in need_sigks:
            actual_sigks.append(skey)
            data_need = need.get('data', {}).get(skey)
            same_limits = compare_limits(ga, data_need)
            if not same_limits:
                mismatch_limits_sigks.add(skey)
        else:
            exceeding_sigks.append(skey)
    actual_sigks = list(set(actual_sigks))
    absent_sigks = [ab for ab in need_sigks if ab not in actual_sigks]
    exceeding_sigks = list(set(exceeding_sigks))
    is_list_actual = not absent_sigks and not exceeding_sigks
    is_data_actual = not mismatch_limits_sigks

    return {'is_actual': is_list_actual and is_data_actual,
            'is_list_actual': is_list_actual,
            'absent': absent_sigks,
            'exceeding': exceeding_sigks,
            'limits_mismatch': list(mismatch_limits_sigks)}


def check_single_check(present, need, sigkey):
    conf_flaps = flaps_from_conf(need, sigkey)
    jug_flaps = extract_flaps(present)
    same_flaps = conf_flaps == jug_flaps

    conf_times = ring_times_from_conf(need, sigkey)
    jug_times = extract_phone_times(present)
    same_times = conf_times == jug_times

    conf_is_user = is_users_from_conf(need, sigkey)
    jug_is_user = alert_is_users_from_juggler_tags(present['tags'])
    same_group = conf_is_user == jug_is_user

    conf_logins = logins_from_conf(need, conf_is_user)
    jug_logins = present.get('golem_resps')
    same_logins = conf_logins == jug_logins or jug_logins is None

    is_same = same_flaps and same_times and same_logins
    return {'same': is_same,
            'same_flaps': same_flaps, 'same_times': same_times,
            'same_logins': same_logins, 'same_group': same_group}


def check_checks(present, need, is_meta):
    """
    :param present: checks from juggler
    :param need: alerts from dm conf
    :return:
    """
    need_sigks = alert_keys_from_conf(need, is_meta=is_meta)
    need_sigks = [ns for ns in need_sigks if should_have_juggler(need, ns)]
    present_sigks = []
    unactual_checks_cnt = 0
    wrong_group_checks = []
    for g_host, gh_data in present.items():
        for juggler_id, jid_data in gh_data.items():
            skey = alert_key_from_juggler_tags(jid_data['tags'])
            present_sigks.append(skey)
            if skey in need_sigks:
                cmp_single_res = check_single_check(jid_data, need, skey)
                if not cmp_single_res['same']:
                    unactual_checks_cnt += 1
                if not cmp_single_res['same_group']:
                    wrong_group_checks.append({'juggler_id': juggler_id, 'golem_host': g_host})
    present_sigks = list(set(present_sigks))
    absent_sigks = [sk for sk in need_sigks if sk not in present_sigks]
    exceeding_sigks = [sk for sk in present_sigks if sk not in need_sigks]
    is_list_actual = not absent_sigks and not exceeding_sigks
    is_data_actual = is_list_actual and not unactual_checks_cnt
    return {'is_actual': is_data_actual, 'is_list_actual': is_list_actual,
            'absent': absent_sigks, 'exceeding': exceeding_sigks,
            'wrong_group': wrong_group_checks}


def generate_alert(service, ctype, key, conf):
    sig_opts = SIGNALS().get(key)
    if not sig_opts:
        raise Exception('signal key %s does not exist' % key)
    limits = conf['data'][key]['limits']
    sig_templ = sig_opts['templ']
    itype = sig_opts['itype']
    gi = GolovanInput()
    gi.GolovanId = 'saas.gen.{ctype}.{service}.{itype}{dcpart}.{key}'\
        .format(ctype=ctype, service=service, itype=itype, key=key, dcpart='')
    gi.Signal = sig_templ.format(service=service, ctype=ctype)
    gi.RealTags = {'itype': itype}
    gi.Limits = limits_conf2yasm(limits)
    if limits.get('avgsec'):
        gi.Limits['avgsec'] = limits['avgsec']
    gi.Descr = 'test alerts'
    return gi
